package com.gaofans.nrpc.client.route.impl;

import com.gaofans.nrpc.client.route.*;
import com.gaofans.nrpc.common.processor.ServiceAuthority;
import com.gaofans.nrpc.common.processor.SimpleEventListener;
import com.gaofans.nrpc.common.processor.Sink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.List;
import java.util.Objects;

/**
 * @author GaoFans
 */
public class LoadBalanceRouter extends Router {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalanceRouter.class);

    private final ServiceStorage storage;
    private final LoadBalance loadBalance;

    public LoadBalanceRouter(int order, RouterPredicate predicate,ServiceStorage storage,LoadBalance loadBalance) {
        super(order, "LoadBalanceRouter", predicate);
        this.storage = Objects.requireNonNull(storage);
        this.loadBalance = loadBalance;
        this.storage.addListener(getName(),new SimpleEventListener<>(new Sink<ServiceEvent<ServiceInstance>>() {
            @Override
            public Sink<ServiceEvent<ServiceInstance>> next(ServiceEvent<ServiceInstance> event) {
                ServiceInstance instance = event.getData();
                ServiceEvent.EventType type = event.getType();
                publishAll(instance.getAuthority(),type);
                return this;
            }

            @Override
            public void complete() {
                LOGGER.debug("LoadBalanceRouter listener {} completed",getName());
            }

            @Override
            public void error(Throwable throwable) {
                LOGGER.error("LoadBalanceRouter listener {} error",getName(),throwable);
            }
        }));
    }

    @Override
    public ServiceAuthority find(URI uri) {
        String serviceId = uri.getHost();
        List<ServiceInstance> instances = storage.getInstances(serviceId);
        if (instances != null && instances.size() > 0){
            ServiceInstance instance = loadBalance.select(serviceId, instances);
            LOGGER.debug("使用服务实例:{}",instance);
            return instance.getAuthority();
        }else {
            LOGGER.error("找不到服务:{}",serviceId);
            throw new IllegalStateException("找不到服务:"+serviceId);
        }
    }



}
